﻿//using Microsoft.EntityFrameworkCore;
//using Microsoft.EntityFrameworkCore.ChangeTracking;
//using Microsoft.EntityFrameworkCore.Metadata;
//using System;
//using System.Linq;
//using System.Linq.Expressions;
//using System.Reflection;
//using Volo.Abp;
//using Volo.Abp.Auditing;
//using Volo.Abp.EntityFrameworkCore;
//using Volo.Abp.Users;
//using Yyd.Domain;

//namespace Yyd.EntityFrameworkCore
//{
//    /// <summary>
//    /// 扩展 abp 的 YddDbContext
//    /// </summary>
//    /// <typeparam name="TDbContext"></typeparam>
//    public abstract class YddDbContext<TDbContext> : AbpDbContext<TDbContext>
//        where TDbContext : DbContext
//    {
//        private readonly ICurrentUser _currentUser;

//        protected YddDbContext(DbContextOptions<TDbContext> options, ICurrentUser currentUser) : base(options)
//        {
//            _currentUser = currentUser;
//        }

//        protected static readonly MethodInfo ConfigureBasePropertiesMethodInfo
//            = typeof(YddDbContext<TDbContext>)
//                .GetMethod(
//                    nameof(ConfigureBaseProperties),
//                    BindingFlags.Instance | BindingFlags.NonPublic
//                );

//        #region 审计赋值

//        protected override void ApplyAbpConceptsForModifiedEntity(EntityEntry entry)
//        {
//            if (entry.State == EntityState.Modified && entry.Properties.Any(x => x.IsModified))
//            {
//                if (entry.Entity is ISoftDelete && entry.Entity.As<ISoftDelete>().IsDeleted)
//                {
//                    SetDeletionAuditProperties(entry);
//                }
//                else
//                {
//                    SetModificationAuditProperties(entry);
//                }
//            }
//        }

//        protected override void SetCreationAuditProperties(EntityEntry entry)
//        {
//            SetCreator(entry.Entity);
//            SetCreateTime(entry.Entity);
//        }

//        protected override void SetModificationAuditProperties(EntityEntry entry)
//        {
//            SetModifier(entry.Entity);
//            SetModificationTime(entry.Entity);
//        }

//        protected override void SetDeletionAuditProperties(EntityEntry entry)
//        {
//            SetDeleter(entry.Entity);
//            SetDeleteTime(entry.Entity);
//        }

//        private void SetCreateTime(object entry)
//        {
//            if (entry is IYydAudit entity)
//            {
//                if (entity.CreationTime == default)
//                {
//                    ObjectHelper.TrySetProperty(entity, x => x.CreationTime, () => Clock.Now);
//                }
//            }
//        }

//        private void SetCreator(object entry)
//        {
//            if (_currentUser == null) return;

//            if (entry is IYydAudit entity)
//            {
//                if (!(entry as IYydAudit).CreatorId.IsNullOrWhiteSpace()) return;
//                ObjectHelper.TrySetProperty(entity, x => x.CreatorId, () => _currentUser.Id.ToString());
//            }
//        }

//        private void SetModificationTime(object entry)
//        {
//            if (entry is IYydAudit entity)
//            {
//                ObjectHelper.TrySetProperty(entity, x => x.LastModificationTime, () => Clock.Now);
//            }
//        }

//        private void SetModifier(object entry)
//        {
//            if (_currentUser == null) return;

//            if (entry is IYydAudit entity)
//            {
//                ObjectHelper.TrySetProperty(entity, x => x.LastModifierId, () => _currentUser.Id.ToString());
//            }
//        }

//        private void SetDeleteTime(object entry)
//        {
//            if (entry is IHasDeletionTime delObj)
//            {
//                delObj.IsDeleted = true;
//                if (delObj.DeletionTime == default)
//                {
//                    ObjectHelper.TrySetProperty(delObj, x => x.DeletionTime, () => Clock.Now);
//                }
//            }
//        }

//        private void SetDeleter(object entry)
//        {
//            if (_currentUser == null) return;

//            if (entry is IYydAudit entity)
//            {
//                ObjectHelper.TrySetProperty(entity, x => x.DeleterId, () => _currentUser.Id.ToString());
//            }
//        }

//        #endregion

//        #region 定义过滤器

//        private void ConfigureBaseProperties<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
//            where TEntity : class
//        {
//            if (mutableEntityType.IsOwned())
//            {
//                return;
//            }

//            ConfigureGlobalFilters<TEntity>(modelBuilder, mutableEntityType);
//        }

//        private void ConfigureGlobalFilters<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType)
//            where TEntity : class
//        {
//            if (mutableEntityType.BaseType == null && ShouldFilterEntity<TEntity>(mutableEntityType))
//            {
//                var filterExpression = CreateFilterExpression<TEntity>();
//                if (filterExpression != null)
//                {
//                    modelBuilder.Entity<TEntity>().HasQueryFilter(filterExpression);
//                }
//            }
//        }

//        private Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
//            where TEntity : class
//        {
//            Expression<Func<TEntity, bool>> expression = null;

//            if (typeof(IHasDeletionTime).IsAssignableFrom(typeof(TEntity)))
//            {
//                expression = e =>
//                    !IsSoftDeleteFilterEnabled ||
//                    EF.Property<bool>(e, nameof(ISoftDelete.IsDeleted)) == false;
//            }

//            return expression;
//        }

//        private bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType) where TEntity : class
//        {
//            if (typeof(IHasDeletionTime).IsAssignableFrom(typeof(TEntity)))
//            {
//                return true;
//            }

//            return false;
//        }

//        #endregion
//    }
//}